﻿using Demo.AttachFileService.Models;
using Demo.AttachFileService.Mongo.Comon;
using Demo.AttachFileService.Services;
using JT808.Protocol;
using JT808.Protocol.Extensions.JTActiveSafety;
using JTActiveSafety.Gateway;
using JTActiveSafety.Gateway.InMemoryMQ;
using JTActiveSafety.Gateway.Services;
using JTActiveSafety.Gateway.Sessions;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Serilog;
using Serilog.Events;
using Serilog.Filters;
using Serilog.Sinks.SystemConsole.Themes;
using System;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;

namespace Demo.AttachFileService
{
    class Program
    {
        private static IConfigurationRoot Configuration;
        static async Task Main(string[] args)
        {
            var serverHostBuilder = new HostBuilder()
                .ConfigureAppConfiguration((hostingContext, config) =>
                {
                    config.SetBasePath(AppDomain.CurrentDomain.BaseDirectory);
                    config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
                    config.Build();
                })
                .ConfigureLogging((context, logging) =>
                {
                    logging.ClearProviders();
                    logging.SetMinimumLevel(LogLevel.Trace);
                })
                .UseServiceProviderFactory(new MyServiceProviderFactory())
                .ConfigureServices((hostContext, services) =>
                {
                    services.AddMemoryCache();
                    services.AddDistributedMemoryCache();
                    //services.AddSingleton<ILoggerFactory, LoggerFactory>();
                    //services.AddSingleton(typeof(ILogger<>), typeof(Logger<>));

                    //var connectionString = Configuration["Data:MongoDB:ConnectionString"];
                    //var dbName = Configuration["Data:MongoDB:DbName"] ?? "AttchFileDB";

                    //services.AddSingleton<IMongoDatabaseProvider>(new MongoDatabaseProvider(connectionString, dbName));
                    //services.AddScoped<MongoDbManager<AlarmInfo>>();
                    //services.AddScoped<MongoDbQuery<AlarmInfo>>();

                    services.AddScoped<ISqliteDbService, SqliteDbService>();
                    services.AddScoped<IAttachFileStorageService, SqliteAttachFileSaveService>();
                    services.AddScoped<IAttachFileRecvService, SqliteAttachFileRecvService>();

 

                    //services.AddSingleton<IAttachFileStorageService, DefaultFileSaveService>();
                    //services.AddSingleton<IAttachFileRecvHandler, MemoryAttachFileRecvHandler>();

                    services.AddJT808Configure()
                        .AddJT808Configure(new JT808_JTActiveSafety_Config())
                        .AddJTActiveSafetyConfigure();

                    services.AddJTActiveSafetyGateway(hostContext.Configuration)
                    .AddTcp();
                    //.AddMsgProducer()
                    //.AddMsgConsumer();

                    //services.AddHostedService<AttachFileHandlerWorker>();
                    //services.AddJT808Configure()
                    //           .AddJTActiveSafetyConfigure();
                })
                .UseSerilog((hostingContext, services, loggerConfiguration) =>
                {
                    loggerConfiguration.ReadFrom.Configuration(hostingContext.Configuration)
                    .Enrich.FromLogContext()//记录相关上下文信息
                                            //.MinimumLevel.Debug()//最小记录级别
                    //.MinimumLevel.Override("Microsoft", LogEventLevel.Information)//对其他日志进行重写,除此之外,目前框架只有微软自带的日志组件
                    .WriteTo.Logger(a =>
                    {
                        a.WriteTo.Logger(b =>
                        {
                            b.Filter.ByIncludingOnly(Matching.FromSource("Microsoft.AspNetCore.Server.Kestrel"))
                            .MinimumLevel.Verbose().WriteTo.Async(c => c.File(AppDomain.CurrentDomain.BaseDirectory + "/logs/Sockets-.log", rollingInterval: RollingInterval.Day));

                            //.WriteTo.Logger(b => {
                            //    b.Filter.ByIncludingOnly(Matching.FromSource("JTActiveSafety.Gateway"))
                            //    .MinimumLevel.Verbose().WriteTo.Async(c => c.File("/logs/all-{Date}.log", rollingInterval: RollingInterval.Day));
                            //});
                        });
                        a.WriteTo.Logger(b =>
                        {
                            b.Filter.ByIncludingOnly(Matching.FromSource("JTActiveSafety.Hosting.Server"))
                            .MinimumLevel.Verbose().WriteTo.Async(c => c.File(AppDomain.CurrentDomain.BaseDirectory + "/logs/SocketsProcessor-.log", rollingInterval: RollingInterval.Day));
                        });

                        a.WriteTo.Logger(b =>
                        {
                            b//.Filter.ByIncludingOnly(Matching.FromSource("JTActiveSafety.Hosting.Server"))
                            //.Filter.ByIncludingOnly( Matching.FromSource("") )
                            .MinimumLevel.Verbose().WriteTo.Async(c => c.Console(theme: SystemConsoleTheme.Colored));
                        });
                    });
                });
                    //.WriteTo.Logger(l3 => l3
                    //.Filter.ByExcluding(Matching.FromSource<BaseController>())
                    //.Filter.ByExcluding(Matching.FromSource<BaseService>())
                    //.MinimumLevel.Verbose()
                    //.WriteTo.Async(c => c.File("/logs/all-{Date}.log", rollingInterval: RollingInterval.Day))
                    //)
 
            //.MinimumLevel.Override("Microsoft", LogEventLevel.Information)
            //.MinimumLevel.Override("JTActiveSafety", LogEventLevel.Debug)
            //.Enrich.FromLogContext()
            //.WriteTo.Console()); ;

            await serverHostBuilder.RunConsoleAsync();
        }
    }

 
    public class MyServiceProviderFactory : IServiceProviderFactory<IServiceProvider>
    {
        public IServiceProvider CreateBuilder(IServiceCollection services)
        {
            return ServiceLocator.Instance = services.BuildServiceProvider();
        }

        public IServiceProvider CreateServiceProvider(IServiceProvider containerBuilder)
        {
            return containerBuilder;
        }
    }
 
    public class DbContextFactory : IDesignTimeDbContextFactory<SqliteDbContext>
    {
        public SqliteDbContext CreateDbContext(string[] args)
        {
            IServiceCollection serviceCollection = new ServiceCollection();
            serviceCollection.AddDbContext<SqliteDbContext>(options => options.UseSqlite("Data Source=F:\\AttachFile\\attachfile.db"));
            var services = serviceCollection.BuildServiceProvider();
            return services.GetService<SqliteDbContext>();
        }
    }
    public static class DbInitializer
    {
        public static void Initialize(SqliteDbContext context)
        {
            context.Database.EnsureCreated();

            //Look for any students.
            if (context.AlarmInfos.Any())
            {
                return;   // DB has been seeded
            }
        }
    }
}
